home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Frameworks / TransSkel++ 305 / Source / TransSkel++.cp < prev   
Text File  |  1996-05-02  |  80KB  |  1,818 lines

  1. /*
  2. ** TransSkel++.cp
  3. **
  4. **  The TransSkel++ module provides a C++ interface to Paul
  5. **  Dubois' TransSkel Application Skeleton.  With TransSkel++,
  6. **  much of the object-oriented flavor of the TransSkel
  7. **  module is massaged into a simple and extendable class 
  8. **  framework.  With not too much fuss, users of TransSkel++
  9. **  may create menus, windows, dialogs, and even applications
  10. **  in as intuitive a way as C++ will allow.
  11. **
  12. **  Compiles under Symantec C/C++ 7.0.4
  13. **                 Metrowerks C/C++ 8
  14. **  Uses TransSkel v3.24
  15. **
  16. **  Fred Dushin
  17. **  email: fadushin@top.cis.syr.edu 
  18. **
  19. **  Release 3.04  May 1, 1996 "Dyslexics untie!"
  20. **  See release notes for details of changes.
  21. */
  22.  
  23. #include <TransSkel++.h>
  24.  
  25. //----------------------------------------------------------------------/
  26. //                        internal headers                              /
  27. //----------------------------------------------------------------------/
  28.  
  29. //----------------------------------------------------------------------/
  30. //  Headers for the mini-list manager                                   /
  31. //  Supports: Dynamic creation and destruction of lists                 /
  32. //            via traditional "cons" cells.                             /
  33. //----------------------------------------------------------------------/
  34.  
  35. typedef void * elt;
  36. typedef struct consCell{
  37.       elt carPtr;
  38.       struct consCell *cdrPtr;
  39.       } consCell, *list;
  40. #define car(l)   ((l)->carPtr)
  41. #define cdr(l)   ((l)->cdrPtr)
  42.  
  43. // A predPtr is a pointer to a predicate (funtion), used as
  44. // a callback for finding items in a list
  45.  
  46. typedef Boolean (*predPtr)( void * item, void * predParams );
  47. static Boolean hasID( void *item, void *predParams );
  48. static Boolean isThis( void *item, void *predParams );
  49.    
  50. // list manager function prototypes
  51.  
  52. static list cons( elt head,elt tail );
  53. static elt findOne( predPtr pred, void * predParams, list l );
  54. static list removeItem( elt item, list l );
  55. static void DestroyCons( consCell * c );
  56. static void DestroyList( list l );
  57.  
  58. //----------------------------------------------------------------------/
  59. // A menuStruct is merely a menuID and a pointer to                     /
  60. // the CMenuObj class instance associated with the menuID.              /
  61. // TransSkel++ maintains a list of menuStructs as menus                 /
  62. // are created and destroyed.  These structs are themselves             /
  63. // dynamically created and deleted.                                     /
  64. //----------------------------------------------------------------------/
  65.  
  66. typedef struct menuStruct{
  67.    short menuID;
  68.    CMenuObj *menu;
  69.    } menuStruct;
  70.  
  71. //----------------------------------------------------------------------/
  72. // The menuList is the list of all menuStructs created                  /
  73. // sApplication is a pointer to the only application                    /
  74. // sAppleMenu is a pointer to the (ONLY) apple menu                     /
  75. //                                                                      /
  76. // appleApplItems is a flag from Paul's SkelApple.c module              /
  77. // It is set to true when the user defines an application               /
  78. // item in the apple menu; o/w it remains false.                        /
  79. // DoAppleMenu is lifted directly from SkelApple.  It's                 /
  80. // defined here and called in place of Paul's corresponding function    /
  81. // so that Apple menu items are properly handled.                       /
  82. // DoMenuCommand is a hack of Paul's function by the same name          /
  83. //----------------------------------------------------------------------/
  84.  
  85. static list          menuList       = nil;
  86. static CApplication  *sApplication  = nil;
  87. static CMenuObj      *sAppleMenu    = nil;
  88. static Boolean       appleApplItems = false;
  89. static pascal void   DoAppleMenu( short menuID, short item );
  90. static Boolean       DoMenuCommand( long command );
  91.  
  92. //----------------------------------------------------------------------/
  93. // The SkelppWindowPropertyID is used to retrieve a structure           /
  94. // used internally by TransSkel++.  The structure includes a            /
  95. // pointer to a CApplObj, ostensibly the CWindow or CDialog             /
  96. // class instance associated with the window or dialog.                 /
  97. // The class instances typically get retrieved in the TransSkel         /
  98. // callbacks in order to call the appropriate class methods.            /
  99. //----------------------------------------------------------------------/
  100.  
  101. #define OFFSET 2704
  102. enum{
  103.    SkelppWindowPropertyID = skelWPropApplBase + OFFSET
  104.    };
  105. typedef struct SkelppWindowProperty{
  106.    CApplObj *obj;   
  107.    // Additional fields for future use (?)
  108.    } SkelppWindowProperty;
  109.  
  110.  
  111. /*---------------------------------------------------------------------*/
  112. /*                       TransSkel callbacks                           */
  113. /*                                                                     */
  114. /*      These "C" functions get passed to TransSkel and get            */
  115. /*      called at the appropriate events.  Except where noted,         */
  116. /*      most callbacks defined here merely call the methods            */
  117. /*      of the appropriate class instance, though typically,           */
  118. /*      these methods will be over-ridden in sub-class definitions.    */
  119. /*---------------------------------------------------------------------*/
  120.  
  121. extern "C"{
  122.  
  123. // CApplication callbacks
  124. static pascal void _doSuspendResume(Boolean inForeground);
  125. static pascal void _doIdle( void );
  126. static pascal Boolean _doEventHook(EventRecord *evt);
  127. static pascal void _doAE(EventRecord *evt);
  128.  
  129. // CMenu callbacks
  130. static pascal void _doMenuClobber(MenuHandle menu);
  131.  
  132. // CAppleMenu callbacks
  133. static pascal void _doAppleSelect( short item );
  134. static pascal void _doAppleClobber(MenuHandle menu);
  135.  
  136. // CWindow callbacks
  137. static pascal void _doWindowMouseClick(Point where, long when, short modifiers);
  138. static pascal void _doWindowKeyClick(short c, short code, short modifiers);
  139. static pascal void _doWindowUpdate (Boolean resized);
  140. static pascal void _doWindowActivate (Boolean active);
  141. static pascal void _doWindowClose(void);
  142. static pascal void _doWindowClobber(void);
  143. static pascal void _doWindowIdle (void);
  144.  
  145. // CDialog callbacks
  146. static pascal Boolean _doDialogFilter(DialogPtr dlog, EventRecord *evt, short *item);
  147. static pascal void _doDialogSelect(DialogPtr dlog, short item);
  148. static pascal void _doDialogClose(void);
  149. static pascal void _doDialogClobber(void);
  150.  
  151. }
  152.  
  153.  
  154. //----------------------------------------------------------------------/
  155. //                        implementation                                /
  156. //----------------------------------------------------------------------/
  157.  
  158.  
  159. //======================================================================/
  160. // The CApplObj Class                                                   /
  161. //                                                                      /
  162. //    Base Class: none                                                  /
  163. //    Methods:  • Error(Str255 errorStr, short code);                   /
  164. //                   Handle errors in TransSkel++                       /
  165. //                                                                      /
  166. //    Description: Every class in TransSkel++ is a subclass             /
  167. //    of the ApplObj base class.  This permits all objects              /
  168. //    to inherit the error handling facilities defined therein.         /
  169. //======================================================================/
  170.  
  171.  
  172. //----------------------------------------------------------------------/
  173. // Error                                                      protected /
  174. //                                                                      /
  175. // Default error handling method.  Calls fatalAlert if fatal error      /
  176. // message passed in error code, then exits program _abnorammly_        /
  177. //                                                                      /
  178. // PARAMETERS                                                           /
  179. //     errorStr:  a pascal string when gets printed in alert box        /
  180. //     code:      an error code                                         /
  181. // RETURN VALUE                                                         /
  182. //     none                                                             /
  183. //----------------------------------------------------------------------/
  184.  
  185. void
  186. CApplObj::Error( Str255 errorStr, short code )
  187. {
  188.     
  189.    switch( code ){
  190.       case Skelpp_noErr:
  191.          break;
  192.       case Skelpp_fatalErr:
  193.          FatalAlert( errorStr );
  194.          ExitToShell();
  195.          break;
  196.       }
  197.  
  198. }
  199.  
  200.  
  201. //----------------------------------------------------------------------/
  202. // FatalAlert                                                   private /
  203. //                                                                      /
  204. // Put up an internally defined alert after beeping.  Also puts up      /
  205. // exit button in alert box and message telling about to exit           /
  206. //                                                                      /
  207. // PARAMETERS                                                           /
  208. //     str:  a pascal string when gets printed in alert box             /
  209. // RETURN VALUE                                                         /
  210. //     none                                                             /
  211. //----------------------------------------------------------------------/
  212.  
  213. void
  214. CApplObj::FatalAlert( Str255 str )
  215. {
  216.    SysBeep( 10 );
  217.    FakeAlert( str, "\p\r\r", "\pPress Exit to quit program\r", nil, 
  218.               1, 1, 0, "\pExit", nil, nil );
  219. }
  220.  
  221.  
  222. //======================================================================/
  223. // The CApplication Class                                               /
  224. //                                                                      /
  225. //    Base Class: CApplObj Class                                        /
  226. //    Methods:  • Run(void);                                            /
  227. //                   Run the application                                /
  228. //              • doEventHook(EventRecord *evt);                        /
  229. //                   Respect the host's event hook                      /
  230. //              • doSuspendResume(Boolean inForeground);                /
  231. //                   Handle suspend/resume events                       /
  232. //              • doIdle(void);                                         /
  233. //                   Handle idle events                                 /
  234. //                                                                      /
  235. //    Description: Every program must have exactly one CApplication     /
  236. //    class (or subclass) instance, which is pointed to by the static   /
  237. //    pointer sApplication.  Typically, a programmer will define        /
  238. //    a subclass of the CApplication class for his or her purposes,     /
  239. //    making it a container for all global storage in the program.      /
  240. //                                                                      /
  241. //    The CApplication class constructor adds an event hook for         /
  242. //    inspecting events before being processed by TransSkel.  This      /
  243. //    event hook is necessary for proper handling of menu events,       /
  244. //    since TransSkel does not have anything for menus like the         /
  245. //    property list it supports for windows and dialogs.                /
  246. //======================================================================/
  247.  
  248.  
  249. //----------------------------------------------------------------------/
  250. // CApplication                                                  public /
  251. //                                                                      /
  252. // The CApplication constructor Initializes TransSkel                   /
  253. // and registers the idle, suspend/resume, and event hook               /
  254. // procedures mentioned above.  A pointer to the application            /
  255. // is initialized to the (sole) instance of this class.                 /
  256. // This pointer is needed in order for TransSkel++ to call              /
  257. // the class's methods.                                                 /
  258. //                                                                      /
  259. // PARAMETERS                                                           /
  260. //     initParams:  initialization parameters passed to SkelInit        /
  261. // RETURN VALUE                                                         /
  262. //     none                                                             /
  263. //----------------------------------------------------------------------/
  264.  
  265. CApplication::CApplication( SkelInitParamsPtr initParams )
  266. {
  267.    if ( !sApplication ){
  268.       SkelInit( initParams );
  269.       
  270.       // Set up internal callbacks
  271.       SkelSetIdle( _doIdle );
  272.       SkelSetSuspendResume( _doSuspendResume );
  273.       SkelSetEventHook( _doEventHook );
  274.       if ( SkelQuery( skelQHasAppleEvents ) ){
  275.          SkelSetAEHandler( _doAE );
  276.          }
  277.       sApplication = this;
  278.       }
  279.    else{
  280.       Error("\pYou may only define one application", Skelpp_fatalErr);
  281.       }
  282. }
  283.  
  284.  
  285. //----------------------------------------------------------------------/
  286. // ~CApplication                                                 public /
  287. //                                                                      /
  288. // The CApplication destructor.                                         /
  289. // Calls SkelCleanup() and sets the global sApplication to nil          /
  290. // (in the unlikely event host defines a new application).              /
  291. //                                                                      /
  292. // PARAMETERS                                                           /
  293. //     none                                                             /
  294. // RETURN VALUE                                                         /
  295. //     none                                                             /
  296. //----------------------------------------------------------------------/
  297.  
  298. CApplication::~CApplication(void)
  299. {
  300.    SkelCleanup();
  301.    sApplication = nil;
  302. }
  303.  
  304.  
  305. /*---------------------------------------------------------------------*/
  306. /*             TransSkel callbacks for CApplication class              */
  307. /*                                                                     */
  308. /*      These "C" functions get passed to TransSkel and get            */
  309. /*      called at the appropriate events.  Except where noted,         */
  310. /*      most callbacks defined here merely call the methods            */
  311. /*      of the appropriate class instance, though typically,           */
  312. /*      these methods will be over-ridden in sub-class definitions.    */
  313. /*---------------------------------------------------------------------*/
  314.  
  315. extern "C"{
  316.  
  317. /*---------------------------------------------------------------------*/
  318. /* _doSuspendResume                                            static  */
  319. /*                                                                     */
  320. /* Call the application's suspend/resume method                        */
  321. /*                                                                     */
  322. /* PARAMETERS                                                          */
  323. /*    as per TransSkel                                                 */
  324. /* RETURN VALUE                                                        */
  325. /*    as per TransSkel                                                 */
  326. /*---------------------------------------------------------------------*/
  327.  
  328. static pascal void 
  329. _doSuspendResume( Boolean inForeground )
  330. {
  331.    if ( sApplication ){
  332.       sApplication->doSuspendResume( inForeground );
  333.       }
  334. }
  335.  
  336.  
  337. /*---------------------------------------------------------------------*/
  338. /* _doIdle                                                     static  */
  339. /*                                                                     */
  340. /* Call the application's idle method                                  */
  341. /*                                                                     */
  342. /* PARAMETERS                                                          */
  343. /*    as per TransSkel                                                 */
  344. /* RETURN VALUE                                                        */
  345. /*    as per TransSkel                                                 */
  346. /*---------------------------------------------------------------------*/
  347.  
  348. static pascal void 
  349. _doIdle(void)
  350. {
  351.    if ( sApplication ){
  352.       sApplication->doIdle();
  353.       }
  354. }
  355.  
  356.  
  357. /*---------------------------------------------------------------------*/
  358. /* _doEventHook                                                static  */
  359. /*                                                                     */
  360. /*   Inspect the event before TransSkel has a chance to.               */
  361. /*   If there was a mouseDown event in the menubar or a                */
  362. /*   command key equivalent, process the event by                      */
  363. /*   doing a menu(Select|Key) and calling the doSelect                 */
  364. /*   method in the menu class instance in the menuList.                */
  365. /*   This is necessary because TransSkel provides no way               */
  366. /*   of informing the callbacks for the menu handlers of               */
  367. /*   the menu being invoked; nor are there menu property               */
  368. /*   lists, as there are for windows and dialogs.                      */
  369. /*                                                                     */
  370. /* PARAMETERS                                                          */
  371. /*    as per TransSkel                                                 */
  372. /* RETURN VALUE                                                        */
  373. /*    as per TransSkel                                                 */
  374. /*---------------------------------------------------------------------*/
  375.  
  376. static pascal Boolean
  377. _doEventHook(EventRecord *evt)
  378. {
  379.    Boolean result = false;
  380.    
  381.    if ( !sApplication )
  382.       return false;
  383.    
  384.    /* First, respect the host's event hook */
  385.    if ( sApplication->doEventHook( evt ) ){
  386.       return true;
  387.       }
  388.    
  389.    /* otherwise, check for menu events */
  390.    switch ( evt->what ){
  391.       case mouseDown:
  392.          GrafPtr evtPort;
  393.          short evtPart;
  394.          Rect appleRect;
  395.  
  396.          evtPart = FindWindow ( evt->where, &evtPort );
  397.  
  398.          if ( evtPart == inMenuBar ){
  399.             /* First call the CApplication's menu hook */
  400.             sApplication->doMenuHook();
  401.             /* Then handle the menu command */
  402.             result = DoMenuCommand( MenuSelect( evt->where ) );
  403.             }
  404.          break;
  405.       
  406.       case keyDown:
  407.       case autoKey:
  408.          char evtChar = evt->message & charCodeMask;
  409.          
  410.          if ( (evt->modifiers & cmdKey) && !SkelCmdPeriod ( evt ) ){
  411.             sApplication->doMenuHook();
  412.             result = DoMenuCommand( MenuKey( evtChar ) );
  413.             }
  414.             break;
  415.       }
  416.    return result;
  417. }
  418.  
  419.  
  420. /*---------------------------------------------------------------------*/
  421. /* _doAE                                                       static  */
  422. /*                                                                     */
  423. /* Call the application's AE method                                    */
  424. /*                                                                     */
  425. /* PARAMETERS                                                          */
  426. /*    as per TransSkel                                                 */
  427. /* RETURN VALUE                                                        */
  428. /*    as per TransSkel                                                 */
  429. /*---------------------------------------------------------------------*/
  430.  
  431. static pascal void 
  432. _doAE( EventRecord *evt )
  433. {
  434.    if ( sApplication ){
  435.       sApplication->doAE( evt );
  436.       }
  437. }
  438.  
  439. } /* extern "C" */
  440.  
  441.  
  442.  
  443. //----------------------------------------------------------------------/
  444. // DoMenuCommand                                                 static /
  445. //                                                                      /
  446. // This definition is adapted from the TransSkel static function by the /
  447. // same name.  It's needed here in order to handle selection of items   /
  448. // in the apple menu properly.                                          /
  449. //                                                                      /
  450. // PARAMETERS                                                           /
  451. //    command: encodes menu/item in long                                /
  452. // RETURN VALUE                                                         /
  453. //    true if a menu was handles; false o/w                             /
  454. //----------------------------------------------------------------------/
  455.  
  456. static Boolean 
  457. DoMenuCommand( long command )
  458. {
  459.    short menuID, item;
  460.    Boolean result = false;
  461.    menuStruct * theMenu;
  462.             
  463.    menuID = HiWord( command );
  464.    item   = LoWord( command );
  465.             
  466.    /* find the menuStruct in menuList which has menuID */
  467.    theMenu = (menuStruct *)findOne( hasID, &menuID, menuList );
  468.    if ( theMenu ){
  469.        /* Treat Apple menu specially (Because of 'DRVR' resources) */
  470.        if ( menuID == skelAppleMenuID ){
  471.           DoAppleMenu( menuID, item );
  472.           }
  473.        else{
  474.           theMenu->menu->doSelect( item );
  475.           }
  476.        result = true;
  477.        }
  478.    HiliteMenu( 0 );
  479.    return result;
  480. }
  481.  
  482.  
  483. //----------------------------------------------------------------------/
  484. // DoAppleMenu                                                   static /
  485. //                                                                      /
  486. // Paul's DoAppleItem proc, with minor modification                     /
  487. // This is lifted directly from SkelApple.c.                            /
  488. //                                                                      /
  489. // PARAMETERS                                                           /
  490. //    menuID: menu ID of apple menu (should be 128)                     /
  491. //    item:   menu item selected                                        /
  492. // RETURN VALUE                                                         /
  493. //    true if a menu was handles; false o/w                             /
  494. //----------------------------------------------------------------------/
  495.  
  496. static pascal void
  497. DoAppleMenu( short menuID, short item )
  498. {
  499. GrafPtr    curPort;
  500. Str255    str;
  501. Handle    h;
  502. short    i;
  503. MenuHandle menu = GetMHandle(menuID);
  504.  
  505.     /*
  506.      * If there are application items, determine if item is one of them.
  507.      * Can tell by tracking backward through the items; if the gray line
  508.      * separating application items and DA's if not found before top of
  509.      * menu is reached, then its an application item, else a DA.  This
  510.      * strategy requires that there be no "-" items in the items string
  511.      * passed to SkelApple().
  512.      */
  513.     if ( appleApplItems )
  514.     {
  515.         for (i = item;  i > 0;  i--)    /* look from current to item 1 */
  516.         {
  517.             GetItem (menu, i, str);
  518.             if (str[0] == 1 && str[1] == '-')
  519.                 break;
  520.         }
  521.         if (i == 0)                    /* reached top without seeing line */
  522.         {
  523.             _doAppleSelect(item);
  524.             return;
  525.         }
  526.     }
  527.  
  528.     /* either no application items or selection isn't one of them */
  529.     GetPort (&curPort);
  530.     GetItem(menu, item, str);            /* get DA name */
  531.     SetResLoad (false);
  532.     h = GetNamedResource ('DRVR', str);
  533.     SetResLoad (true);
  534.     if (h != (Handle) nil)
  535.     {
  536. #if skelUnivHeaders
  537.         ReserveMem (GetResourceSizeOnDisk (h) + 0x1000);
  538. #else
  539.         /* can't use new name for this one in non-universal headers */
  540.         ReserveMem (SizeResource (h) + 0x1000);
  541. #endif
  542.         (void) OpenDeskAcc (str);            /* open it */
  543.     }
  544.     SetPort (curPort);
  545. }
  546.  
  547.  
  548. //----------------------------------------------------------------------/
  549. // hasID                                                         static /
  550. //                                                                      /
  551. // List handler callback                                                /
  552. //                                                                      /
  553. // PARAMETERS                                                           /
  554. //    item:        current item on list                                 /
  555. //    predParams:  parameter passed through list handler                /
  556. // RETURN VALUE                                                         /
  557. //    true if item has same id as that passed through predParames;      /
  558. //    false, o/w                                                        /
  559. //----------------------------------------------------------------------/
  560.  
  561. static Boolean 
  562. hasID(void *item, void *predParams)
  563. {
  564.    return( ((menuStruct *)item)->menuID == *(short *)predParams );
  565. }
  566.  
  567.  
  568. //----------------------------------------------------------------------/
  569. // isThis                                                        static /
  570. //                                                                      /
  571. // List handler callback                                                /
  572. //                                                                      /
  573. // PARAMETERS                                                           /
  574. //    item:        current item on list                                 /
  575. //    predParams:  parameter passed through list handler                /
  576. // RETURN VALUE                                                         /
  577. //    true if item is the same as that passed through predParames;      /
  578. //    false, o/w                                                        /
  579. //----------------------------------------------------------------------/
  580.  
  581. static Boolean 
  582. isThis(void *item, void *predParams)
  583. {
  584.    return( ((menuStruct *)item)->menu == (CMenuObj *)predParams );
  585. }
  586.  
  587.  
  588.  
  589. //======================================================================/
  590. // The CMenu Class                                                      /
  591. //                                                                      /
  592. //    Base Class: CMenuObj Class                                        /
  593. //    Methods:  • doSelect(short item);                                 /
  594. //                   Handle item selections in menu                     /
  595. //                                                                      /
  596. //    Member variables:                                                 /
  597. //       • MenuHandle menu; (protected)                                 /
  598. //          A handle to the QD menu structure                           /
  599. //                                                                      /
  600. //    Description: The CMenu class is used for standard (anything       /
  601. //    not an apple) menu handling.  Users of TransSkel++ will typically /
  602. //    create subclasses of the CMenu class for each menu in the         /
  603. //    application (e.g., CFileMenu, CEditMenu, etc.)  Because TransSkel /
  604. //    treates the Apple menu specially, a special CAppleMenu class      /
  605. //    is defined below.                                                 /
  606. //======================================================================/
  607.  
  608.  
  609. //----------------------------------------------------------------------/
  610. // CMenu                                                         public /
  611. //                                                                      /
  612. // The CMenu constructor.                                               /
  613. //                                                                      /
  614. // PARAMETERS                                                           /
  615. //     menuID:  resource id of new menu                                 /
  616. //     subMenu: true if is a submenu                                    /
  617. //     drawBar: draw the menubar after creation (usually false)         /
  618. // RETURN VALUE                                                         /
  619. //     none                                                             /
  620. //----------------------------------------------------------------------/
  621.  
  622. CMenu::CMenu( short menuID, Boolean subMenu, Boolean drawBar )
  623. {
  624.    menuStruct *ms;
  625.    
  626.    // Create the menu
  627.    menu = GetMenu( menuID );
  628.    if ( !menu ){
  629.       Error( "\pCould not allocate memory for menu", Skelpp_fatalErr );
  630.       return;
  631.       }
  632.  
  633.    // register it with TransSkel
  634.    if ( !SkelMenu( menu,
  635.                    nil,              /* item selection handler */
  636.                    nil,              /* disposal function */
  637.                    subMenu,          /* true if hierarchichal */
  638.                    drawBar )         /* true if draw after alloc'd */
  639.                          ){
  640.       Error( "\pCould not register menu with TransSkel", 
  641.              Skelpp_fatalErr );
  642.       DisposeMenu( menu );
  643.       return;
  644.       }
  645.    
  646.    // Create a menuStruct to hold menuID and pointer to class instance
  647.    if ( !(ms = (menuStruct *)NewPtr( sizeof( menuStruct ) )) ){
  648.       Error( "\pCould not allocate internal menu list handler", 
  649.              Skelpp_fatalErr );
  650.       DisposeMenu( menu );
  651.       return;
  652.       }
  653.    
  654.    // intitialize fields and place on menuList
  655.    ms->menuID = menuID;
  656.    ms->menu = this;
  657.    menuList = cons( ms, menuList );
  658. }
  659.  
  660.  
  661. //----------------------------------------------------------------------/
  662. // ~CMenu                                                        public /
  663. //                                                                      /
  664. // The CMenu destructor.                                                /
  665. //    First get rid of the menuStruct on the menuList, if it exists     /
  666. //    Then call SkelRmveWindow, which deletes the menu from the         /
  667. //    menubar, redraws the menubar, and then calls the clobber          /
  668. //    proc for the menu, which in this case will be _doMenuClobber      /
  669. //    (which frees space tied up by menu).  This is safe,               /
  670. //    assuming the user has not called SkelRmveMenu or SkelCleanup      /
  671. //    _before_ deleting the menu instance.                              /
  672. //                                                                      /
  673. // PARAMETERS                                                           /
  674. //     none                                                             /
  675. // RETURN VALUE                                                         /
  676. //     none                                                             /
  677. //----------------------------------------------------------------------/
  678.  
  679. CMenu::~CMenu(void)
  680. {
  681.    menuStruct *ms;
  682.    
  683.    ms = (menuStruct *)findOne( isThis, this, menuList );
  684.    if ( ms ){
  685.       menuList = removeItem( ms , menuList );
  686.       DisposePtr( (Ptr)ms );
  687.       }
  688.    SkelRmveMenu( menu );
  689.    DisposeMenu( menu );
  690. }
  691.  
  692.  
  693. /*---------------------------------------------------------------------*/
  694. /*             TransSkel callbacks for CMenu class                     */
  695. /*                                                                     */
  696. /*      These "C" functions get passed to TransSkel and get            */
  697. /*      called at the appropriate events.  Except where noted,         */
  698. /*      most callbacks defined here merely call the methods            */
  699. /*      of the appropriate class instance, though typically,           */
  700. /*      these methods will be over-ridden in sub-class definitions.    */
  701. /*---------------------------------------------------------------------*/
  702.  
  703. extern "C"{
  704.  
  705. /*---------------------------------------------------------------------*/
  706. /* _doMenuClobber                                              static  */
  707. /*                                                                     */
  708. /* For future use                                                      */
  709. /*                                                                     */
  710. /* PARAMETERS                                                          */
  711. /*    as per TransSkel                                                 */
  712. /* RETURN VALUE                                                        */
  713. /*    as per TransSkel                                                 */
  714. /*---------------------------------------------------------------------*/
  715.  
  716. static pascal void 
  717. _doMenuClobber( MenuHandle menu ){}
  718.  
  719. } /* extern "C" */
  720.  
  721.  
  722. //======================================================================/
  723. // The CAppleMenu Class                                                 /
  724. //                                                                      /
  725. //    Base Class: CMenuObj Class                                        /
  726. //    Methods:  • doSelect(short item);                                 /
  727. //                   Handle item selections in Apple menu               /
  728. //                                                                      /
  729. //    Description: The CAppleMenu class is used for managing the        /
  730. //    apple menu.  Because TransSkel treats the apple menu specially,   /
  731. //    (with SkelApple), a special class constructor is needed.  Also,   /
  732. //    TransSkel provides for no destructors for Apple menus, so         /
  733. //    the CAppleMenu class has no clobber method.                       /
  734. //======================================================================/
  735.  
  736.  
  737. //----------------------------------------------------------------------/
  738. // CAppleMenu                                                    public /
  739. //                                                                      /
  740. // The CAppleMenu constructor.                                          /
  741. //                                                                      /
  742. // PARAMETERS                                                           /
  743. //     items:  Pascal String for about menu item(s)                     /
  744. // RETURN VALUE                                                         /
  745. //     none                                                             /
  746. //----------------------------------------------------------------------/
  747.  
  748. CAppleMenu::CAppleMenu( const StringPtr items )
  749. {
  750.     menuStruct *ms;
  751.  
  752.     /* 024 = apple character */
  753.     menu = NewMenu( skelAppleMenuID, (StringPtr) "\p\024" );
  754.     if (items != (StringPtr) nil && items[0] > 0)
  755.     {
  756.         /* application has own items in menu */
  757.         appleApplItems = true;
  758.         /* add items */
  759.         AppendMenu( menu, items );
  760.         /* add gray line */
  761.         AppendMenu( menu, (StringPtr) "\p(-" );
  762.     }
  763.     AddResMenu( menu, 'DRVR' );        /* add desk accessories */
  764.     (void) SkelMenu ( menu, _doAppleSelect, _doAppleClobber, 
  765.                       false, false );
  766.  
  767.     if ( !sAppleMenu ){
  768.        if ( !(ms = (menuStruct *)NewPtr( sizeof( menuStruct ) )) ){
  769.           Error( "\pCould not allocate internal menu list handler", 
  770.                  Skelpp_fatalErr );
  771.           DisposeMenu( menu );
  772.           return;
  773.           }
  774.  
  775.        ms->menuID = 128;
  776.        ms->menu = this;
  777.        menuList = cons( ms, menuList );
  778.        sAppleMenu = this;
  779.        }
  780.     else{
  781.        Error( "\pYou may only have one apple menu", 
  782.               Skelpp_fatalErr );
  783.        }
  784. }
  785.  
  786.  
  787. //----------------------------------------------------------------------/
  788. // ~CAppleMenu                                                   public /
  789. //                                                                      /
  790. // The CAppleMenu destructor.                                           /
  791. //    First get rid of the menuStruct on the menuList, if it exists,    /
  792. //    and restore globals to their original state (just in case         /
  793. //    user decides to make a new apple menu on-the-fly).                /
  794. //    Then call SkelRmveWindow, which deletes the menu from the         /
  795. //    menubar, redraws the menubar, and then calls the clobber          /
  796. //    proc for the menu, which in this case will be _doAppleClobber     /
  797. //    (which frees space tied up by menu)                               /
  798. //                                                                      /
  799. // PARAMETERS                                                           /
  800. //     none                                                             /
  801. // RETURN VALUE                                                         /
  802. //     none                                                             /
  803. //----------------------------------------------------------------------/
  804.  
  805. CAppleMenu::~CAppleMenu( void )
  806. {
  807.    menuStruct *ms;
  808.    
  809.    ms = (menuStruct *)findOne( isThis, this, menuList );
  810.    if ( ms ){
  811.       menuList = removeItem( ms , menuList );
  812.       DisposePtr( (Ptr)ms );
  813.       }
  814.  
  815.    sAppleMenu = nil;         /* restore */
  816.    appleApplItems = false;   /* globals */
  817.    
  818.    SkelRmveMenu( menu );
  819. }
  820.  
  821.  
  822. /*---------------------------------------------------------------------*/
  823. /*             TransSkel callbacks for CAppleMenu class                */
  824. /*                                                                     */
  825. /*      These "C" functions get passed to TransSkel and get            */
  826. /*      called at the appropriate events.  Except where noted,         */
  827. /*      most callbacks defined here merely call the methods            */
  828. /*      of the appropriate class instance, though typically,           */
  829. /*      these methods will be over-ridden in sub-class definitions.    */
  830. /*---------------------------------------------------------------------*/
  831.  
  832. extern "C"{
  833.  
  834. /*---------------------------------------------------------------------*/
  835. /* _doAppleSelect                                              static  */
  836. /*                                                                     */
  837. /* Handle selections in apple menu                                     */
  838. /* With the current version, this is completely gratuitous             */
  839. /*                                                                     */
  840. /* PARAMETERS                                                          */
  841. /*    as per TransSkel                                                 */
  842. /* RETURN VALUE                                                        */
  843. /*    as per TransSkel                                                 */
  844. /*---------------------------------------------------------------------*/
  845.  
  846. static pascal void 
  847. _doAppleSelect( short item )
  848. {
  849.    sAppleMenu->doSelect(item);
  850. }
  851.  
  852.  
  853. /*---------------------------------------------------------------------*/
  854. /* _doAppleClobber                                             static  */
  855. /*                                                                     */
  856. /* Free up dynamically allocated menu, if it exists                    */
  857. /*                                                                     */
  858. /* PARAMETERS                                                          */
  859. /*    as per TransSkel                                                 */
  860. /* RETURN VALUE                                                        */
  861. /*    as per TransSkel                                                 */
  862. /*---------------------------------------------------------------------*/
  863.  
  864. static pascal void 
  865. _doAppleClobber( MenuHandle menu )
  866. {
  867.    if ( menu ) 
  868.       DisposeMenu( menu );
  869. }
  870.  
  871.  
  872. } /* extern "C" */
  873.  
  874.  
  875.  
  876. //======================================================================/
  877. // The CWindow Class                                                    /
  878. //                                                                      /
  879. //    Base Class: CApplObj Class                                        /
  880. //    Methods:  • doMouseClick(Point where, long when, short modifiers);/
  881. //                   Handle mouse clicks in window                      /
  882. //              • doKeyClick(short c, short code, short modifiers);     /
  883. //                   Handle key clicks in window                        /
  884. //              • doUpdate(Boolean resized);                            /
  885. //                   Handle Update events in window                     /
  886. //              • doActivate(Boolean active);                           /
  887. //                   Handle Activate events in window                   /
  888. //              • doClose(void);                                        /
  889. //                   Handle closing window (default method              /
  890. //                   hides window via HideWindow())                     /
  891. //              • doIdle(void);                                         /
  892. //                   Handle idle events in window                       /
  893. //              • doShow(void);                                         /
  894. //                   Display window (Calls Show/SelectWindow())         /
  895. //              • GetWindowPtr(void);                                   /
  896. //                   Returns WindowPtr to QD window struct              /
  897. //                                                                      /
  898. //    Member variables:                                                 /
  899. //       • WindowPtr wind; (protected)                                  /
  900. //          A pointer to the QD window structure                        /
  901. //                                                                      /
  902. //    Description: The CWindow class is the base class for all window   /
  903. //    objects in TransSkel++.  Users will typically create subclasses   /
  904. //    of the CWindow class (e.g., CDrawWindow, CStatusWindow, etc.)     /
  905. //    and override any of the above methods and/or create new ones.     /
  906. //======================================================================/
  907.  
  908.  
  909. //----------------------------------------------------------------------/
  910. // CWindow                                                       public /
  911. //                                                                      /
  912. // The CWindow constructor.                                             /
  913. //                                                                      /
  914. // PARAMETERS                                                           /
  915. //    wStorage                                                          /
  916. //    boundsRect                                                        /
  917. //    tile                                                              /
  918. //    visible                                                           /
  919. //    procID                                                            /
  920. //    behind             as per IM:ToolBox Essentials                   /
  921. //    goAway                                                            /
  922. //    refCon                                                            /
  923. //    frontIdle  Call idle event proc only if frontmost                 /
  924. // RETURN VALUE                                                         /
  925. //     none                                                             /
  926. //----------------------------------------------------------------------/
  927.  
  928. CWindow::CWindow( Ptr wStorage,
  929.                   Rect *boundsRect,
  930.                   Str255 title,
  931.                   Boolean visible,
  932.                   int procID,
  933.                   WindowPtr behind,
  934.                   Boolean goAway,
  935.                   long refCon,
  936.                   Boolean frontIdle )
  937. {
  938.    SkelppWindowProperty **p;
  939.  
  940.    if ( SkelQuery( skelQHasColorQD ) ){
  941.       wind = NewCWindow( wStorage, boundsRect, title, visible, 
  942.                          procID, behind, goAway, refCon );
  943.       }
  944.    else{
  945.       wind = NewWindow(  wStorage, boundsRect, title, visible, 
  946.                          procID, behind, goAway, refCon);
  947.       }
  948.    
  949.    if ( !wind ){
  950.       Error( "\pCould not allocate memory for wind", 
  951.              Skelpp_fatalErr );
  952.       return;
  953.       }
  954.  
  955.    if ( !SkelWindow ( wind,
  956.             _doWindowMouseClick,        /* mouse click handler       */
  957.             _doWindowKeyClick,          /* key click handler         */
  958.             _doWindowUpdate,            /* update event handler      */
  959.             _doWindowActivate,          /* activate event handler    */
  960.             _doWindowClose,             /* close box click handler   */
  961.             nil,                        /* disposal function         */
  962.             _doWindowIdle,              /* idle-time handler         */
  963.             frontIdle )                 /* idle only when frontmost  */
  964.             ){
  965.       Error( "\pCould not register wind with TransSkel", 
  966.              Skelpp_fatalErr );
  967.       DisposeWindow( wind );
  968.       return;
  969.       }
  970.    
  971.    // Create a SkelppWindowProperty and place a handle to it on the
  972.    // property list of the new window, indexed by SkelppWindowPropertyID
  973.    if ( !(p = (SkelppWindowProperty **)
  974.               NewHandle( sizeof( SkelppWindowProperty ) )) ){
  975.       Error( "\pCould not allocate memory for window property", 
  976.              Skelpp_fatalErr );
  977.       SkelRmveWind( wind );
  978.       DisposeWindow( wind );
  979.       return;
  980.       }
  981.    
  982.    (**p).obj = this;
  983.    if ( !SkelAddWindProp( wind, SkelppWindowPropertyID, (long)p ) ){
  984.       Error( "\pCould not put Skel++ window property on property list", 
  985.              Skelpp_fatalErr );
  986.       SkelRmveWind( wind );
  987.       DisposeWindow( wind );
  988.       return;
  989.       }
  990. }
  991.  
  992.  
  993. //----------------------------------------------------------------------/
  994. // CWindow                                                       public /
  995. //                                                                      /
  996. // The CWindow constructor.                                             /
  997. //                                                                      /
  998. // PARAMETERS                                                           /
  999. //    windID                                                            /
  1000. //    wStorage                                                          /
  1001. //    behind             as per IM:ToolBox Essentials                   /
  1002. //    frontIdle  Call idle event proc only if frontmost                 /
  1003. // RETURN VALUE                                                         /
  1004. //     none                                                             /
  1005. //----------------------------------------------------------------------/
  1006.  
  1007. CWindow::CWindow( short windID, 
  1008.                   Ptr wStorage, 
  1009.                   WindowPtr behind, 
  1010.                   Boolean frontIdle )
  1011. {
  1012.    SkelppWindowProperty **p;
  1013.  
  1014.    if ( SkelQuery( skelQHasColorQD ) ){
  1015.       wind = GetNewCWindow( windID, wStorage, behind );
  1016.       }
  1017.    else{
  1018.       wind = GetNewCWindow( windID, wStorage, behind );
  1019.       }
  1020.    
  1021.    if ( !wind ){
  1022.       Error( "\pCould not allocate memory for wind", 
  1023.              Skelpp_fatalErr );
  1024.       return;
  1025.       }
  1026.  
  1027.    if ( !SkelWindow ( wind,
  1028.             _doWindowMouseClick,        /* mouse click handler       */
  1029.             _doWindowKeyClick,          /* key click handler         */
  1030.             _doWindowUpdate,            /* update event handler      */
  1031.             _doWindowActivate,          /* activate event handler    */
  1032.             _doWindowClose,             /* close box click handler   */
  1033.             nil,                        /* disposal function         */
  1034.             _doWindowIdle,              /* idle-time handler         */
  1035.             frontIdle )                 /* idle only when frontmost  */
  1036.             ){
  1037.       Error( "\pCould not register wind with TransSkel", 
  1038.              Skelpp_fatalErr );
  1039.       DisposeWindow( wind );
  1040.       return;
  1041.       }
  1042.    
  1043.    // Create a SkelppWindowProperty and place a handle to it on the
  1044.    // property list of the new window, indexed by SkelppWindowPropertyID
  1045.    if ( !(p = (SkelppWindowProperty **)
  1046.               NewHandle( sizeof( SkelppWindowProperty ) )) ){
  1047.       Error( "\pCould not allocate memory for window property", 
  1048.              Skelpp_fatalErr );
  1049.       SkelRmveWind( wind );
  1050.       DisposeWindow( wind );
  1051.       return;
  1052.       }
  1053.    
  1054.    (**p).obj = this;
  1055.    if ( !SkelAddWindProp( wind, SkelppWindowPropertyID, (long)p ) ){
  1056.       Error( "\pCould not put Skel++ window property on property list", 
  1057.              Skelpp_fatalErr );
  1058.       SkelRmveWind( wind );
  1059.       DisposeWindow( wind );
  1060.       return;
  1061.       }
  1062. }
  1063.  
  1064.  
  1065. //----------------------------------------------------------------------/
  1066. // ~CWindow                                                      public /
  1067. //                                                                      /
  1068. // The CWindow destructor.                                              /
  1069. //                                                                      /
  1070. // PARAMETERS                                                           /
  1071. //     none                                                             /
  1072. // RETURN VALUE                                                         /
  1073. //     none                                                             /
  1074. //----------------------------------------------------------------------/
  1075.  
  1076. CWindow::~CWindow( void )
  1077. {
  1078.    SkelppWindowProperty **p;
  1079.    
  1080.    if ( wind ){
  1081.       p = (SkelppWindowProperty **)
  1082.              SkelGetWindPropData( wind, SkelppWindowPropertyID );
  1083.       SkelRmveWindProp( wind, SkelppWindowPropertyID );
  1084.       DisposeHandle( (Handle)p );
  1085.       SkelRmveWind( wind );
  1086.       DisposeWindow( wind );
  1087.       }
  1088. }
  1089.  
  1090.  
  1091. //----------------------------------------------------------------------/
  1092. // doShow                                                     protected /
  1093. //                                                                      /
  1094. // Default doShow method                                                /
  1095. //                                                                      /
  1096. // PARAMETERS                                                           /
  1097. //     none                                                             /
  1098. // RETURN VALUE                                                         /
  1099. //     none                                                             /
  1100. //----------------------------------------------------------------------/
  1101.  
  1102. void 
  1103. CWindow::doShow( void )
  1104. {
  1105.    ShowWindow( wind );
  1106.    SelectWindow( wind );
  1107. }
  1108.  
  1109.  
  1110.  
  1111. //----------------------------------------------------------------------/
  1112. // GetCWindow                                                           /
  1113. //                                                                      /
  1114. // returns a pointer to the class instance associated with wind         /
  1115. //                                                                      /
  1116. // PARAMETERS                                                           /
  1117. //     wind: a WindowPtr                                                /
  1118. // RETURN VALUE                                                         /
  1119. //     pointer to CWindow instance associated with wind, if it          /
  1120. //     exists; nil o/w                                                  /
  1121. //----------------------------------------------------------------------/
  1122.  
  1123. CWindow * 
  1124. GetCWindow( WindowPtr wind )
  1125. {
  1126.    SkelppWindowProperty **p = nil;
  1127.    
  1128.    if ( wind ){
  1129.       p = (SkelppWindowProperty **)
  1130.             SkelGetWindPropData( wind, SkelppWindowPropertyID );
  1131.       }
  1132.    return( p ? (CWindow *)((**p).obj) : nil );
  1133. }
  1134.  
  1135.  
  1136. /*---------------------------------------------------------------------*/
  1137. /*             TransSkel callbacks for CWindow class                   */
  1138. /*                                                                     */
  1139. /*      These "C" functions get passed to TransSkel and get            */
  1140. /*      called at the appropriate events.  Except where noted,         */
  1141. /*      most callbacks defined here merely call the methods            */
  1142. /*      of the appropriate class instance, though typically,           */
  1143. /*      these methods will be over-ridden in sub-class definitions.    */
  1144. /*---------------------------------------------------------------------*/
  1145.  
  1146. extern "C" {
  1147.  
  1148. /*---------------------------------------------------------------------*/
  1149. /* _doWindowMouseClick                                         static  */
  1150. /*                                                                     */
  1151. /* Handle mouseclicks in window                                        */
  1152. /* Calls corresponding class instance's doMouseClick method.           */
  1153. /*                                                                     */
  1154. /* PARAMETERS                                                          */
  1155. /*    as per TransSkel                                                 */
  1156. /* RETURN VALUE                                                        */
  1157. /*    as per TransSkel                                                 */
  1158. /*---------------------------------------------------------------------*/
  1159.  
  1160. static pascal void 
  1161. _doWindowMouseClick( Point where, long when, short modifiers )
  1162. {
  1163.    WindowPtr wind;
  1164.    CWindow *w;
  1165.   
  1166.    GetPort(&wind);
  1167.    if ( wind && (w = GetCWindow( wind )) ){
  1168.       w->doMouseClick( where, when, modifiers );
  1169.       }
  1170. }
  1171.  
  1172.  
  1173. /*---------------------------------------------------------------------*/
  1174. /* _doWindowKeyClick                                           static  */
  1175. /*                                                                     */
  1176. /* Handle keyclicks in window                                          */
  1177. /* Calls corresponding class instance's doKeyClick method.             */
  1178. /*                                                                     */
  1179. /* PARAMETERS                                                          */
  1180. /*    as per TransSkel                                                 */
  1181. /* RETURN VALUE                                                        */
  1182. /*    as per TransSkel                                                 */
  1183. /*---------------------------------------------------------------------*/
  1184.  
  1185. static pascal void 
  1186. _doWindowKeyClick( short c, short code, short modifiers )
  1187. {
  1188.    WindowPtr wind;
  1189.    CWindow *w;
  1190.   
  1191.    GetPort(&wind);
  1192.    if ( w = GetCWindow( wind ) ){
  1193.       w->doKeyClick( c, code, modifiers );
  1194.       }   
  1195. }
  1196.  
  1197.  
  1198. /*---------------------------------------------------------------------*/
  1199. /* _doWindowUpdate                                             static  */
  1200. /*                                                                     */
  1201. /* Handle window updates                                               */
  1202. /* Calls corresponding class instance's doUpdate method.               */
  1203. /*                                                                     */
  1204. /* PARAMETERS                                                          */
  1205. /*    as per TransSkel                                                 */
  1206. /* RETURN VALUE                                                        */
  1207. /*    as per TransSkel                                                 */
  1208. /*---------------------------------------------------------------------*/
  1209.  
  1210. static pascal void 
  1211. _doWindowUpdate( Boolean resized )
  1212. {
  1213.    WindowPtr wind;
  1214.    CWindow *w;
  1215.   
  1216.    GetPort( &wind );
  1217.    if ( w = GetCWindow( wind ) ){
  1218.       w->doUpdate( resized );
  1219.       }   
  1220. }
  1221.  
  1222.  
  1223. /*---------------------------------------------------------------------*/
  1224. /* _doWindowActivate                                           static  */
  1225. /*                                                                     */
  1226. /* Handle window activates                                             */
  1227. /* Calls corresponding class instance's doActivate method.             */
  1228. /*                                                                     */
  1229. /* PARAMETERS                                                          */
  1230. /*    as per TransSkel                                                 */
  1231. /* RETURN VALUE                                                        */
  1232. /*    as per TransSkel                                                 */
  1233. /*---------------------------------------------------------------------*/
  1234.  
  1235. static pascal void 
  1236. _doWindowActivate ( Boolean active )
  1237. {
  1238.    WindowPtr wind;
  1239.    CWindow *w;
  1240.   
  1241.    GetPort( &wind );
  1242.    if ( w = GetCWindow( wind ) ){
  1243.       w->doActivate( active );
  1244.       }   
  1245. }
  1246.  
  1247.  
  1248. /*---------------------------------------------------------------------*/
  1249. /* _doWindowClose                                              static  */
  1250. /*                                                                     */
  1251. /* Handle closebox selections                                          */
  1252. /* Calls corresponding class instance's doClose method.                */
  1253. /*                                                                     */
  1254. /* PARAMETERS                                                          */
  1255. /*    as per TransSkel                                                 */
  1256. /* RETURN VALUE                                                        */
  1257. /*    as per TransSkel                                                 */
  1258. /*---------------------------------------------------------------------*/
  1259.  
  1260. static pascal void 
  1261. _doWindowClose( void )
  1262. {
  1263.    WindowPtr wind;
  1264.    CWindow *w;
  1265.   
  1266.    GetPort( &wind );
  1267.    if ( w = GetCWindow( wind ) ){
  1268.       w->doClose();
  1269.       }
  1270. }
  1271.  
  1272.  
  1273. /*---------------------------------------------------------------------*/
  1274. /* _doWindowIdle                                               static  */
  1275. /*                                                                     */
  1276. /* Handle idle events in window                                        */
  1277. /* Calls corresponding class instance's doIdle method.                 */
  1278. /*                                                                     */
  1279. /* PARAMETERS                                                          */
  1280. /*    as per TransSkel                                                 */
  1281. /* RETURN VALUE                                                        */
  1282. /*    as per TransSkel                                                 */
  1283. /*---------------------------------------------------------------------*/
  1284.  
  1285. static pascal void 
  1286. _doWindowIdle( void )
  1287. {
  1288.    WindowPtr wind;
  1289.    CWindow *w;
  1290.   
  1291.    GetPort( &wind );
  1292.    if ( w = GetCWindow( wind ) ){
  1293.       w->doIdle();
  1294.       }   
  1295. }
  1296.  
  1297. } /* extern "C" */
  1298.  
  1299.  
  1300. //======================================================================/
  1301. // The CDialog Class                                                    /
  1302. //                                                                      /
  1303. //    Base Class: CApplObj Class                                        /
  1304. //    Methods:  • doFilter(EventRecord *evt, short *item);              /
  1305. //                   dialog filter proc                                 /
  1306. //              • doSelect(short item);                                 /
  1307. //                   Handle item selections in dialog                   /
  1308. //              • doClose(void);                                        /
  1309. //                   Handle closing dialog (default method              /
  1310. //                   hides window via HideWindow())                     /
  1311. //              • doShow(void);                                         /
  1312. //                   Display dialog (Calls Show/SelectWindow())         /
  1313. //              • GetDialogPtr(void);                                   /
  1314. //                   Returns DialogPtr to QD dialog struct              /
  1315. //                                                                      /
  1316. //    Member variables:                                                 /
  1317. //       • DialogPtr dlog; (protected)                                  /
  1318. //          A pointer to the QD dialog structure                        /
  1319. //                                                                      /
  1320. //    Description: The CDialog class is the base class for all dialog   /
  1321. //    objects in TransSkel++.  Users will typically create subclasses   /
  1322. //    of the CDialog class (e.g., CAboutDialog, CSettingDialog, etc.)   /
  1323. //    and override any of the above methods and/or create new ones.     /
  1324. //======================================================================/
  1325.  
  1326.  
  1327. //----------------------------------------------------------------------/
  1328. // CDialog                                                       public /
  1329. //                                                                      /
  1330. // The CDialog constructor.                                             /
  1331. //                                                                      /
  1332. // PARAMETERS                                                           /
  1333. //    dStorage                                                          /
  1334. //    boundsRect                                                        /
  1335. //    title                                                             /
  1336. //    visible                                                           /
  1337. //    procID                                                            /
  1338. //    behind             as per IM:ToolBox Essentials                   /
  1339. //    goAway                                                            /
  1340. //    refCon                                                            /
  1341. //    items                                                             /
  1342. // RETURN VALUE                                                         /
  1343. //     none                                                             /
  1344. //----------------------------------------------------------------------/
  1345.  
  1346. CDialog::CDialog( Ptr dStorage,
  1347.                   Rect *boundsRect,
  1348.                   Str255 title,
  1349.                   Boolean visible,
  1350.                   int procID,
  1351.                   DialogPtr behind,
  1352.                   Boolean goAway,
  1353.                   long refCon,
  1354.                   Handle items )
  1355. {
  1356.    SkelppWindowProperty **p;
  1357.    
  1358.    if ( SkelQuery( skelQHasColorQD ) ){
  1359.       dlog = NewCDialog( dStorage, boundsRect, title, visible, 
  1360.                          procID, behind, goAway, refCon, items );
  1361.       }
  1362.    else{
  1363.       dlog = NewDialog( dStorage, boundsRect, title, visible, 
  1364.                         procID, behind, goAway, refCon, items);
  1365.       }
  1366.  
  1367.    if ( !dlog ){
  1368.       Error( "\pCould not allocate memory for dlog", 
  1369.              Skelpp_fatalErr );
  1370.       return;
  1371.       }
  1372.  
  1373.    if ( !SkelDialog ( dlog,                 /* dialog pointer */
  1374.             _doDialogFilter,                /* filterproc */
  1375.             _doDialogSelect,                /* item handler */
  1376.             _doDialogClose,                 /* close handler */
  1377.             nil )                           /* dispose dlog */
  1378.             ){
  1379.       Error( "\pCould not register dlog with TransSkel", 
  1380.              Skelpp_fatalErr );
  1381.       DisposeWindow( dlog );
  1382.       return;
  1383.       }
  1384.    
  1385.    // Create a SkelppWindowProperty and place a handle to it on the
  1386.    // property list of the new window, indexed by SkelppWindowPropertyID
  1387.    if ( !(p = (SkelppWindowProperty **)
  1388.               NewHandle( sizeof( SkelppWindowProperty ) )) ){
  1389.       Error( "\pCould not allocate memory for window property", 
  1390.              Skelpp_fatalErr );
  1391.       SkelRmveDlog( dlog );
  1392.       DisposeDialog( dlog );
  1393.       return;
  1394.       }
  1395.    
  1396.    (**p).obj = this;
  1397.    if ( !SkelAddWindProp( dlog, SkelppWindowPropertyID, (long)p ) ){
  1398.       Error( "\pCould not put Skel++ window property on property list", 
  1399.              Skelpp_fatalErr );
  1400.       SkelRmveDlog( dlog );
  1401.       DisposeDialog( dlog );
  1402.       return;
  1403.       }
  1404. }
  1405.  
  1406.  
  1407. //----------------------------------------------------------------------/
  1408. // CDialog                                                       public /
  1409. //                                                                      /
  1410. // The CDialog constructor.                                             /
  1411. //                                                                      /
  1412. // PARAMETERS                                                           /
  1413. //    windID                                                            /
  1414. //    wStorage                                                          /
  1415. //    behind             as per IM:ToolBox Essentials                   /
  1416. // RETURN VALUE                                                         /
  1417. //     none                                                             /
  1418. //----------------------------------------------------------------------/
  1419.  
  1420. CDialog::CDialog(short dlogID, Ptr wStorage, WindowPtr behind)
  1421. {
  1422.    SkelppWindowProperty **p;
  1423.    
  1424.    // No GetNewCDialog ...
  1425.    dlog = GetNewDialog( dlogID, wStorage, behind );
  1426.  
  1427.    if ( !dlog ){
  1428.       Error( "\pCould not allocate memory for dlog", 
  1429.              Skelpp_fatalErr);
  1430.       return;
  1431.       }
  1432.  
  1433.    if ( !SkelDialog ( dlog,                 /* dialog pointer */
  1434.             _doDialogFilter,                /* filterproc */
  1435.             _doDialogSelect,                /* item handler */
  1436.             _doDialogClose,                 /* close handler */
  1437.             nil )                           /* dispose dlog */
  1438.             ){
  1439.       Error( "\pCould not register dlog with TransSkel", 
  1440.              Skelpp_fatalErr );
  1441.       DisposeWindow( dlog );
  1442.       return;
  1443.       }
  1444.    
  1445.    // Create a SkelppWindowProperty and place a handle to it on the
  1446.    // property list of the new window, indexed by SkelppWindowPropertyID
  1447.    if ( !(p = (SkelppWindowProperty **)
  1448.               NewHandle( sizeof( SkelppWindowProperty ) )) ){
  1449.       Error( "\pCould not allocate memory for window property", 
  1450.              Skelpp_fatalErr );
  1451.       SkelRmveDlog( dlog );
  1452.       DisposeDialog( dlog );
  1453.       return;
  1454.       }
  1455.    
  1456.    (**p).obj = this;
  1457.    if ( !SkelAddWindProp( dlog, SkelppWindowPropertyID, (long)p ) ){
  1458.       Error( "\pCould not put Skel++ window property on property list", 
  1459.              Skelpp_fatalErr );
  1460.       SkelRmveDlog( dlog );
  1461.       DisposeDialog( dlog );
  1462.       return;
  1463.       }
  1464. }
  1465.  
  1466.  
  1467. //----------------------------------------------------------------------/
  1468. //~ CDialog                                                      public /
  1469. //                                                                      /
  1470. // The CDialog constructor.                                             /
  1471. //    Call SkelRmveDlog, which deletes the TransSkel internal           /
  1472. //    dialog handler, and then calls the clobber                        /
  1473. //    proc for the dlog, which in this case will be _doDialogClobber    /
  1474. //    (which frees space tied up by dlog).  This is safe,               /
  1475. //    assuming the user has not called SkelRmveDlog or SkelCleanup      /
  1476. //    _before_ deleting the dlog instance.                              /
  1477. //                                                                      /
  1478. // PARAMETERS                                                           /
  1479. //     none                                                             /
  1480. // RETURN VALUE                                                         /
  1481. //     none                                                             /
  1482. //----------------------------------------------------------------------/
  1483.  
  1484. CDialog::~CDialog( void )
  1485. {
  1486.    SkelppWindowProperty **p;
  1487.    
  1488.    if ( dlog ){
  1489.       p = (SkelppWindowProperty **)
  1490.           SkelGetWindPropData( dlog, SkelppWindowPropertyID );
  1491.       SkelRmveWindProp( dlog, SkelppWindowPropertyID );
  1492.       DisposeHandle( (Handle)p );
  1493.       SkelRmveDlog( dlog );
  1494.       DisposeDialog( dlog );
  1495.       }
  1496. }
  1497.  
  1498.  
  1499. //----------------------------------------------------------------------/
  1500. // doShow                                                     protected /
  1501. //                                                                      /
  1502. // Default doShow method                                                /
  1503. //                                                                      /
  1504. // PARAMETERS                                                           /
  1505. //     none                                                             /
  1506. // RETURN VALUE                                                         /
  1507. //     none                                                             /
  1508. //----------------------------------------------------------------------/
  1509.  
  1510. void
  1511. CDialog::doShow(void)
  1512. {
  1513.    ShowWindow(dlog);
  1514.    SelectWindow(dlog);
  1515. }
  1516.  
  1517.  
  1518. //----------------------------------------------------------------------/
  1519. // GetCDialog                                                           /
  1520. //                                                                      /
  1521. // returns a pointer to the class instance associated with dlog         /
  1522. //                                                                      /
  1523. // PARAMETERS                                                           /
  1524. //     dlog: a DialogPtr                                                /
  1525. // RETURN VALUE                                                         /
  1526. //     pointer to CDialog instance associated with dlog, if it          /
  1527. //     exists; nil o/w                                                  /
  1528. //----------------------------------------------------------------------/
  1529.  
  1530. CDialog * 
  1531. GetCDialog( DialogPtr dlog )
  1532. {
  1533.    SkelppWindowProperty **p = nil;
  1534.    
  1535.    if ( dlog ){
  1536.       p = (SkelppWindowProperty **)
  1537.           SkelGetWindPropData( dlog, SkelppWindowPropertyID );
  1538.       }
  1539.    return( p ? (CDialog *)(**p).obj : nil );
  1540. }
  1541.  
  1542.  
  1543. /*---------------------------------------------------------------------*/
  1544. /*             TransSkel callbacks for CDialog class                   */
  1545. /*                                                                     */
  1546. /*      These "C" functions get passed to TransSkel and get            */
  1547. /*      called at the appropriate events.  Except where noted,         */
  1548. /*      most callbacks defined here merely call the methods            */
  1549. /*      of the appropriate class instance, though typically,           */
  1550. /*      these methods will be over-ridden in sub-class definitions.    */
  1551. /*---------------------------------------------------------------------*/
  1552.  
  1553. extern "C" {
  1554.  
  1555. /*---------------------------------------------------------------------*/
  1556. /* _doDialogFilter                                             static  */
  1557. /*                                                                     */
  1558. /* The dialog's filter proc                                            */
  1559. /* Calls corresponding class instance's doFilter method.               */
  1560. /*                                                                     */
  1561. /* PARAMETERS                                                          */
  1562. /*    as per TransSkel                                                 */
  1563. /* RETURN VALUE                                                        */
  1564. /*    as per TransSkel                                                 */
  1565. /*---------------------------------------------------------------------*/
  1566.  
  1567. static pascal Boolean 
  1568. _doDialogFilter(DialogPtr dlog, EventRecord *evt, short *item)
  1569. {
  1570.    CDialog *d;
  1571.    Boolean b = false;
  1572.  
  1573.    if ( d = GetCDialog( dlog ) ){
  1574.       b = d->doFilter( evt, item );
  1575.       }
  1576.    
  1577.    return b;
  1578. }
  1579.  
  1580.  
  1581. /*---------------------------------------------------------------------*/
  1582. /* _doDialogSelect                                             static  */
  1583. /*                                                                     */
  1584. /* The dialog's item selection proc                                    */
  1585. /* Calls corresponding class instance's doSelect method.               */
  1586. /*                                                                     */
  1587. /* PARAMETERS                                                          */
  1588. /*    as per TransSkel                                                 */
  1589. /* RETURN VALUE                                                        */
  1590. /*    as per TransSkel                                                 */
  1591. /*---------------------------------------------------------------------*/
  1592.  
  1593. static pascal void 
  1594. _doDialogSelect( DialogPtr dlog, short item )
  1595. {
  1596.    CDialog *d;
  1597.  
  1598.    if ( d = GetCDialog( dlog ) ){
  1599.       d->doSelect( item );
  1600.       }
  1601. }
  1602.  
  1603.  
  1604. /*---------------------------------------------------------------------*/
  1605. /* _doDialogClose                                              static  */
  1606. /*                                                                     */
  1607. /* The dialog's item close proc                                        */
  1608. /* Calls corresponding class instance's doClose method.                */
  1609. /*                                                                     */
  1610. /* PARAMETERS                                                          */
  1611. /*    as per TransSkel                                                 */
  1612. /* RETURN VALUE                                                        */
  1613. /*    as per TransSkel                                                 */
  1614. /*---------------------------------------------------------------------*/
  1615.  
  1616. static pascal void 
  1617. _doDialogClose( void )
  1618. {
  1619.    CDialog *d;
  1620.    DialogPtr dlog;
  1621.    
  1622.    GetPort( &dlog );
  1623.    if ( d = GetCDialog( dlog ) ){
  1624.       d->doClose();
  1625.       }   
  1626. }
  1627.  
  1628. } /* extern "C" */
  1629.  
  1630.  
  1631. //----------------------------------------------------------------------/
  1632. //                                                                      /
  1633. //                             List Handler                             /
  1634. //                                                                      /
  1635. //    This mini list handler creates dynamic lists using traditional    /
  1636. //    cons cells which point to (perhaps) dynamically allocated         /
  1637. //    data objects.  For the most part, lists are assumed to be         /
  1638. //    flat (no nested lists), and the cdr of last cons cell in the list /
  1639. //    is assumed to point to nil.  OK as long as cons(itemn, nil) is    /
  1640. //    called first.                                                     /
  1641. //                                                                      /
  1642. //    list -->+---+---+   +---+---+            +---+-+                  /
  1643. //            | o | o---->| o | o----> ... --->| o |\|                  /
  1644. //            +-|-+---+   +-|-+---+            +-|-+-+                  /
  1645. //              v           v                    v                      /
  1646. //             item1       item2                itemn                   /
  1647. //                                                                      /
  1648. //       The following functions provide a minimal set of routines      /
  1649. //       for handling the static menuList which keeps track of which    /
  1650. //       menus have been defined in TransSkel++.  Based on Fred's       /
  1651. //       List Manager.  Supports:                                       /
  1652. //         • list cons(elt head, elt tail);                             /
  1653. //             Returns the cons of head and tail, as a consCell.        /
  1654. //             It is the user's responsibility to destroy cell.         /
  1655. //         • elt findOne(predPtr pred, void * predParams, list l);      /
  1656. //             Find first item in list which satisfies pred(predParams) /
  1657. //         • list removeItem(elt item, list l);                         /
  1658. //             Remove consCell in list which points to item.            /
  1659. //         • void DestroyCons(consCell * c);                            /
  1660. //             Deallocate consCell (assuming created via cons)          /
  1661. //             Leaves item pointed to by cons intact.                   /
  1662. //         • void DestroyList(list l);                                  /
  1663. //             Deallocate all consCells in list (assuming created       /
  1664. //             via cons) Leaves items pointed to by cons' intact.       /
  1665. //----------------------------------------------------------------------/
  1666.  
  1667.  
  1668. //----------------------------------------------------------------------/
  1669. // cons                                                          static /
  1670. //                                                                      /
  1671. // returns    -->+---+---+                                              /
  1672. //               | o | o----> tail                                      /
  1673. //               +-|-+---+                                              /
  1674. //                 v                                                    /
  1675. //                head                                                  /
  1676. //                                                                      /
  1677. // PARAMETERS                                                           /
  1678. //    head                                                              /
  1679. //    tail                                                              /
  1680. // RETURN VALUE                                                         /
  1681. //    new list with head in position 1                                  /
  1682. //----------------------------------------------------------------------/
  1683.  
  1684. static list 
  1685. cons( elt head, elt tail )
  1686. {
  1687.   list newCell;
  1688.  
  1689.   if ( !(newCell = (list)NewPtr( sizeof( consCell ) )) ){
  1690.     return nil;
  1691.     }
  1692.  
  1693.   car(newCell) = head;
  1694.   cdr(newCell) = (consCell *)tail;
  1695.  
  1696.   return newCell;
  1697. }
  1698.  
  1699.  
  1700. //----------------------------------------------------------------------/
  1701. // findOne                                                       static /
  1702. //                                                                      /
  1703. // returns a pointer to first element in l statisfying predicate pred;  /
  1704. // nil if none found.                                                   /
  1705. //                                                                      /
  1706. // PARAMETERS                                                           /
  1707. //    pred:        predicate to apply to elts in list                   /
  1708. //    predParams:  parameter passed to pred                             /
  1709. //    l:           list in which to search                              /
  1710. // RETURN VALUE                                                         /
  1711. //    new list with head in position 1                                  /
  1712. //----------------------------------------------------------------------/
  1713.  
  1714. static elt 
  1715. findOne( predPtr pred, void * predParams, list l )
  1716. {
  1717.    Boolean found = false;
  1718.    
  1719.    /*
  1720.     * short circuit evaluation
  1721.     */
  1722.    while ( l && !(found = (*pred)( car(l), predParams )) ){
  1723.       l = cdr(l);
  1724.       }
  1725.    
  1726.    return (found ? car(l) : nil);
  1727. }
  1728.  
  1729.  
  1730. //----------------------------------------------------------------------/
  1731. // removeItem                                                    static /
  1732. //                                                                      /
  1733. // removes item from list (destructive).  Returns pointer to the        /
  1734. // orginal list.                                                        /
  1735. //                                                                      /
  1736. // PARAMETERS                                                           /
  1737. //    item:  item to be removed                                         /
  1738. //    l:     list from which to remove item                             /
  1739. // RETURN VALUE                                                         /
  1740. //    new list with item removed; old list if item not in list          /
  1741. //----------------------------------------------------------------------/
  1742.  
  1743. static list 
  1744. removeItem( elt item, list l )
  1745. {
  1746.    Boolean found = false;
  1747.    list prev = nil, origList = l;
  1748.    
  1749.    /*
  1750.     * short circuit evaluation
  1751.     */
  1752.    while ( l && !(found = (item == car(l))) ){
  1753.       prev = l;
  1754.       l = cdr(l);
  1755.       }
  1756.    
  1757.    if ( found ){
  1758.       /* l is non-nil */
  1759.       if ( prev ){
  1760.          if ( cdr(l) ){ /* l is in middle of list */
  1761.             cdr(prev) = cdr(l);
  1762.             }
  1763.          else{ /* l is last item in list */
  1764.             cdr(prev) = nil;
  1765.             }
  1766.          }
  1767.       else{ /* l is first item in list */
  1768.          origList = cdr(l);
  1769.          }
  1770.       DestroyCons( l );
  1771.       }
  1772.    
  1773.    return origList;
  1774. }
  1775.  
  1776.  
  1777. //----------------------------------------------------------------------/
  1778. // DestroyCons                                                   static /
  1779. //                                                                      /
  1780. // Deallocates memory for consCell c                                    /                                                        /
  1781. //                                                                      /
  1782. // PARAMETERS                                                           /
  1783. //    c: cons cell to be destroyed                                      /
  1784. // RETURN VALUE                                                         /
  1785. //    none                                                              /
  1786. //----------------------------------------------------------------------/
  1787.  
  1788. static void 
  1789. DestroyCons( consCell * c )
  1790. {   
  1791.    if ( c )
  1792.       DisposePtr( (Ptr)c );
  1793. }
  1794.  
  1795.  
  1796. //----------------------------------------------------------------------/
  1797. // DestroyList                                                   static /
  1798. //                                                                      /
  1799. // Deallocates memory for each consCell in List                         /                                                        /
  1800. //                                                                      /
  1801. // PARAMETERS                                                           /
  1802. //    l: list to be destroyed                                           /
  1803. // RETURN VALUE                                                         /
  1804. //    none                                                              /
  1805. //----------------------------------------------------------------------/
  1806. static void 
  1807. DestroyList( list l )
  1808. {
  1809.    list tmpList;
  1810.  
  1811.  
  1812.    while ( l ){
  1813.       tmpList = (list)cdr(l);
  1814.       DestroyCons( l );
  1815.       l = tmpList;
  1816.       }
  1817. }
  1818.